/**
 *  test_list.c - Test codes for list_t and its functions.
 *                It runs on Windows or Linux.
 *
 *  Copyright (C) 2008  ZhangHu
 *  All rights reserved.
 *  E-MAIL: anmnmnly@gmail.com
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


#include <stdlib.h>
#include <stdio.h>


#include "cunit/Automated.h"
#include "test_list.h"
#include "kernel/list.c"


static void test_add_node_list_rear_0(void) {
    list_t *_head = 0;
    list_t *_pnew = 0;

    add_node_list_rear(_head, _pnew);
}



static void test_add_node_list_rear_1(void) {
    struct list _head_0 = {0};
    list_t *_head = &_head_0;
    list_t *_pnew = 0;

    add_node_list_rear(_head, _pnew);
}



static void test_add_node_list_rear_2(void) {
    list_t *_head = 0;
    struct list _pnew_0 = {0};
    list_t *_pnew = &_pnew_0;

    add_node_list_rear(_head, _pnew);
}



static void test_add_node_list_rear_3(void) {
    list_t *_head = NULL, *_pnew = NULL;

    struct list _head_0;
    struct list _pnew_1;

    list_node_init(&_head_0);

    _head = &_head_0;
    _pnew = &_pnew_1;

    add_node_list_rear(_head, _pnew);
    CU_ASSERT_PTR_EQUAL(_head_0.next, &_pnew_1);
    CU_ASSERT_PTR_EQUAL(_head_0.prev, &_pnew_1);
}




static void test_del_node_list_0(void) {
    list_t *_head = 0;
    list_t *_pdel = 0;

    list_t *_result = del_node_list(_head, _pdel);
    CU_ASSERT_PTR_NULL(_result);
}



static void test_del_node_list_1(void) {
    struct list _head_0 = {0};
    list_t *_head = &_head_0;

    list_t *_pdel = 0;

    list_t *_result = del_node_list(_head, _pdel);
    CU_ASSERT_PTR_NULL(_result);
}



static void test_del_node_list_2(void) {
    list_t *_head = 0;
    struct list _pdel_0 = {0};
    list_t *_pdel = &_pdel_0;

    list_t *_result = del_node_list(_head, _pdel);
    CU_ASSERT_PTR_NULL(_result);
}



static void test_del_node_list_3(void) {
    list_t _head;
    list_t _pdel;
    list_t *_result = NULL;

    list_node_init(&_head);
    add_node_list_rear(&_head, &_pdel);
    _result = del_node_list(&_head, &_pdel);

    CU_ASSERT_PTR_EQUAL(_result, &_pdel);
}



static void test_list_node_init_0(void) {
    list_t *_node = 0;
    list_node_init(_node);
}



static void test_list_node_init_1(void) {
    struct list _node_0 = {0};
    list_t *_node = &_node_0;

    list_node_init(_node);
    CU_ASSERT_PTR_EQUAL(_node->next, _node);
    CU_ASSERT_PTR_EQUAL(_node->prev, _node);
}



#define NODE_NUM 20

static list_t head;
static list_t *rear = NULL;


static void test_create_list(void) {
    int i;
    struct node *p = NULL;
    list_t *list;

    for(i=0; i<NODE_NUM; i++) {
        if((p = (struct node*)malloc(sizeof(struct node))) == NULL) {
            printf("malloc is failed in create_list");
            break;
        } else {
            p->value = NODE_NUM - i - 1;
            add_node_list_rear(&head, &p->link);
        }
    }
    rear = &p->link; // pointer to the last node of list.


    i = 0;
    list = head.prev;

    do {
        p = mac_find_entry(list, struct node, link);
        CU_ASSERT_EQUAL(p->value, i++);
        list = list->prev;
    }while(list != head.prev);
}



static void test_destory_list(void) {
    struct node *p = NULL;
    list_t *list = head.next;

    while(list != &head) {
        list = del_node_list(&head, list);
        p = mac_find_entry(list, struct node, link);
        free(p);
        list = head.next;
    }
}



static void test_delete_first_node(void) {
    struct node *p = NULL;
    list_t *list = head.next;

    list = del_node_list(&head, list);
    p = mac_find_entry(list, struct node, link);
    CU_ASSERT_EQUAL(p->value, NODE_NUM - 1);
    free(p);
}



static void test_delete_rear_node(void) {
    struct node *p = NULL;
    int i = 1;
    list_t *list = NULL;

    rear = del_node_list(&head, rear);
    p = mac_find_entry(rear, struct node, link);
    CU_ASSERT_EQUAL(p->value, 0);
    free(p);

    list = head.prev;
    do {
        p = mac_find_entry(list, struct node, link);
        CU_ASSERT_EQUAL(p->value, i++);
        list = list->prev;
    }while(list != head.prev);
}



int test_list_init(void) {
    printf("list test ...\n\n");
    list_node_init(&head);

    return(0);
}



int test_list_clean(void) {
    printf("list test is over!\n\n");
    return(0);
}



CU_TestInfo test_list_cases[] = {
    {"test_add_node_list_rear_0", test_add_node_list_rear_0},
    {"test_add_node_list_rear_1", test_add_node_list_rear_1},
    {"test_add_node_list_rear_2", test_add_node_list_rear_2},
    {"test_add_node_list_rear_3", test_add_node_list_rear_3},
    {"test_del_node_list_0", test_del_node_list_0},
    {"test_del_node_list_1", test_del_node_list_1},
    {"test_del_node_list_2", test_del_node_list_2},
    {"test_del_node_list_3", test_del_node_list_3},
    {"test_list_node_init_0", test_list_node_init_0},
    {"test_list_node_init_1", test_list_node_init_1},
    {"test_create_list", test_create_list},
    {"test_delete_first_node", test_delete_first_node},
    {"test_delete_rear_node", test_delete_rear_node},
    {"test_destory_list", test_destory_list},
    CU_TEST_INFO_NULL
};

